package cn.juque.jdfsystem.threads;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.juque.common.base.BaseResponseVO;
import cn.juque.common.constants.MessageEnum;
import cn.juque.common.fastjson.abstracts.AbstractTypeReference;
import cn.juque.common.utils.FastJsonUtil;
import cn.juque.jdfsystem.cache.ConfigInfoCache;
import cn.juque.jdfsystem.cache.RegisterInfoCache;
import cn.juque.jdfsystem.contants.UrlConstants;
import cn.juque.jdfsystem.entity.RegisterInfo;
import cn.juque.jdfsystem.enums.ConfigCodeEnum;
import cn.juque.jdfsystem.vo.registerinfo.RegisterInfoListVO;
import cn.juque.lucenecandy.cache.IpCache;
import cn.juque.lucenecandy.core.utils.SignatureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author juque
 * @version 1.0.0
 * <ul>
 *     <li>RegisterLoadThreadPool</li>
 * </ul>
 * @date 2024-01-30
 **/
@Slf4j
@Component("registerLoadThreadPool")
public class RegisterLoadThreadPool {

    private static final ThreadFactory THREAD_FACTORY = ThreadUtil.newNamedThreadFactory("reg-load-", true);

    private static final ScheduledExecutorService EXECUTOR =
            new ScheduledThreadPoolExecutor(1, THREAD_FACTORY, new ThreadPoolExecutor.DiscardPolicy());

    @Resource
    private IpCache ipCache;

    @Resource
    private RegisterInfoCache registerInfoCache;

    @Resource
    private ConfigInfoCache configInfoCache;

    /**
     * 初始化
     */
    public void init() {
        EXECUTOR.scheduleWithFixedDelay(this::load, 0, 30, TimeUnit.SECONDS);
    }

    private void load() {
        try {
            List<String> ips = this.ipCache.listValidIp(false);
            Map<String, BaseResponseVO<List<RegisterInfoListVO>>> map = this.ipCache.batchPost(ips,
                    SignatureUtil.buildUrl(UrlConstants.MESSAGE_REGISTER_LOAD),
                    new AbstractTypeReference<BaseResponseVO<List<RegisterInfoListVO>>>() {
                    }, this.createBody());
            Map<String, RegisterInfo> registerMap = MapUtil.newHashMap();
            map.forEach((k, v) -> {
                if (!MessageEnum.OK.getCode().equals(v.getCode()) || CollUtil.isEmpty(v.getData())) {
                    return;
                }
                List<RegisterInfo> list = BeanUtil.copyToList(v.getData(), RegisterInfo.class);
                list.forEach(f -> registerMap.put(f.getIp(), f));
            });
            this.registerInfoCache.putRegister(CollUtil.newArrayList(registerMap.values()));
        } catch (Exception e) {
            log.error("load register error", e);
        }
    }

    private String createBody() {
        String content = FastJsonUtil.toJsonString(this.registerInfoCache.listAllRegister());
        String value = this.configInfoCache.getValue(ConfigCodeEnum.REGISTER_AES_KEY.getCode());
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, Base64.decode(value));
        return aes.encryptBase64(content);
    }
}
